Rewrites axiom at the depth depth, transforms it into a symbol, and preserves only valid-symbols. If gen-lsystem is activated without valid-symbols, the rewritings are transformed as they are. Rewrite rules are defined with defsym function. L-system provides an elegant way to generate classical fractals like von Koch snowflakes, dragon curves and Peano and Hilbert space filling curves, that model the growth of living organisms.
(initdef)
(defsym g '(g f x < + g > < - g >))
(defsym x '(x < - f f f > < + f f f > f x))
(defsym - '-)
(defsym + '+)
(defsym < '<)
(defsym > '>)
(gen-lsystem g 2 '(f + - < >))
--> (f e e e g g g f g e)
Or using a :tree.
(initdef 'another-tree)
(defsym g '(g f x < - g > < + g >) :tree 'another-tree)
(defsym x '(x < + f f f > < - f f f > f x) :tree 'another-tree)
(defsym - '- :tree 'another-tree)
(defsym + '+ :tree 'another-tree)
(defsym < '< :tree 'another-tree)
(defsym > '> :tree 'another-tree)
(gen-lsystem g 2 '(f + - < >) 'another-tree)
--> (f g g g e e e f e g)
(gen-lsystem g 2 '(f + - < >))
--> (f e e e g g g f g e)
To use L-system to build melodies, you can use directly the output, or rescale it to a new range.
(setq melody (symbol-scale '(a k)
(gen-lsystem g 2 '(f + - < >))))
To control velocities, use
(setq velocity-pattern
(vector-smooth 3
(symbol-to-vector
(gen-lsystem g 2 '(f + - < >)))))
To build chords use symbols-to-tonality. For rhythms use combine symbol-to-vector and vector-scale.
def-grammar equivalence:
(def-grammar 'example-above
g (g f x < - g > < + g >)
x (x < + f f f > < - f f f > f x)
- '-
+ '+
< '<
> '>
)
Examples
; koch-curve
(def-grammar 'koch-curve
axiom (f + f + f + f)
f (f + f - f - f f + f + f - f)
- (-)
+ (+)
< (<)
> (>)
)
(gen-lsystem axiom 3 '(f + - < >) 'koch-curve)
; hilbert curve
(def-grammar 'hilbert-curve
axiom (x)
x (- y f + x f x + f y -)
y (+ x f - y f y - f x +)
- (-)
+ (+)
< (<)
> (>)
)
(gen-lsystem axiom 5 '(f + - < >) 'hilbert-curve)
; peano curve
(def-grammar 'peano-curve
axiom (x)
x (x f y f x + f + y f x f y - f - x f y f x)
y (y f x f y - f - x f y f x + f + y f x f y)
- (-)
+ (+)
< (<)
> (>)
)
(gen-lsystem axiom 3 '(f + - < >) 'peano-curve)
; dragon curve
(def-grammar 'dragon-curve
axiom (f x)
x (x + y f)
y (- f x - y)
- (-)
+ (+)
< (<)
> (>)
)
(gen-lsystem axiom 7 '(f + - < >) 'dragon-curve)
Dragon does not produce anything useful because the 2D rules happens to map here so that it all makes the curve going down.
One idea is to make the production rules randomly using defsym, for example
(defsym f (generate-random-production-rules) :tree 'random-rules)